<template>
  <el-form v-if="isFormInit" ref="form" :model="formData" :rules="formRules" :label-width="labelWidth" :class="column === 'double' ? 'double-column' : 'single-column'">
    <el-form-item
      v-for="(item, index) in formList"
      :key="index"
      :label="item.label"
      :prop="item.prop">

        <!-- text -->
        <el-input
          v-if="item.type === FORM_TYPE_TEXT || (item.type ?? '') === ''"
          v-model="formData[item.prop]"
          :placeholder="setPlaceholder(item)"
          :disabled="item.disabled || formDisabled" />
          
        <!-- number -->
        <el-input-number
          v-else-if="item.type === FORM_TYPE_NUMBER"
          v-model="formData[item.prop]"
          :min="item.min"
          :max="item.max"
          :step="item.step"
          :placeholder="setPlaceholder(item)"
          :disabled="item.disabled || formDisabled" />

        <!-- password -->
        <el-input
            v-else-if="item.type === FORM_TYPE_PASSWORD"
            v-model="formData[item.prop]"
            show-password
            :placeholder="setPlaceholder(item)"
            :disabled="item.disabled || formDisabled" />

        <!-- textarea -->
        <el-input
            v-else-if="item.type === FORM_TYPE_TEXTAREA"
            type="textarea"
            v-model="formData[item.prop]"
            :placeholder="setPlaceholder(item)"
            :autosize="{ minRows: 5, maxRows: 10 }"
            :disabled="item.disabled || formDisabled" />

        <!-- select -->
        <el-select
          v-else-if="item.type === FORM_TYPE_SELECT"
          v-model="formData[item.prop]"
          :placeholder="setPlaceholder(item)"
          :disabled="item.disabled || formDisabled"
          @change="handleSelectChange(item)">
          <el-option
            v-for="item in item.options"
            :key="item.value"
            :label="item.label"
            :value="item.value"></el-option>
        </el-select>

        <!-- date-picker 日期 -->
        <el-date-picker
          v-else-if="item.type === FORM_TYPE_DATE"
          type="date"
          v-model="formData[item.prop]"
          :placeholder="setPlaceholder(item)"
          :disabled="item.disabled || formDisabled"
        ></el-date-picker>

        <!-- cascader 联级下拉 -->
        <el-cascader
          v-else-if="item.type === FORM_TYPE_CASCADER"
          v-model="formData[item.prop]"
          :disabled="item.disabled || formDisabled"
          :placeholder="setPlaceholder(item)"
          :options="item.options"
          :props="{ expandTrigger: item.expandTrigger || 'hover' }"
          :clearable="true">
        </el-cascader>


        <!-- file文件 -->
        <div
          v-else-if="item.type === FORM_TYPE_FILE"
          class="file__input__wrapper"
          :class="{'disabled': item.disabled || formDisabled}">
          <div class="file-list">
            <div v-for="(file, index) in formData[item.prop]" :key="file.uid" class="file-item">
              <span>{{ file.name }}</span>
              <span class="close-btn iconfont icon-close" @click="removeFile(item.prop, index)"></span>
            </div>
          </div>
          <div v-if="formData[item.prop] == null || formData[item.prop].length == 0" class="placeholder">{{ setPlaceholder(item) }}</div>
          <el-upload
            v-model="formData[item.prop]"
            action="#"
            :disabled="item.disabled || formDisabled"
            :accept="item.accept"
            :show-file-list="false"
            :auto-upload="false"
            :on-change="(file, fileList) => {handleChangeFile(item, file, fileList)}"
            :multiple="true">
              <div class="upload-btn" :class="{'disabled': item.disabled || formDisabled}">浏览</div>
          </el-upload>

        </div>

    </el-form-item>
  </el-form>
</template>

<script>
export default {
  props: {
    labelWidth: {
      type: String,
      default: '80px'
    },
    formList: {
      type: Array,
      required: true
    },
    formRules: {
      type: Object,
      default: () => ({})
    },
    formDisabled: {
      type: Boolean,
      default: false,
    },
    // 指定表单单列显示还是双列显示
    column: {
      type: String,
      default: 'double'
    }
  },
  data () {
    return {
      FORM_TYPE_TEXT: 'text',
      FORM_TYPE_NUMBER: 'number',
      FORM_TYPE_PASSWORD: 'password',
      FORM_TYPE_TEXTAREA: 'textarea',
      FORM_TYPE_SELECT: 'select',
      FORM_TYPE_DATE: 'date',
      FORM_TYPE_RADIO: 'radio',
      FORM_TYPE_CHECKBOX: 'checkbox',
      FORM_TYPE_CHECKBOX_GROUP: 'checkboxGroup',
      FORM_TYPE_CASCADER: 'cascader',
      FORM_TYPE_FILE: 'file',
      
      formData: {},
      isFormInit: false
    }
  },
  methods: {
    // 表单数据初始化
    initForm() {
        let formData = {}
        this.formList.forEach(item => {
            const { type, prop } = item

            switch (type) {
              case this.FORM_TYPE_FILE:
              case this.FORM_TYPE_CHECKBOX_GROUP:
                formData[prop] = []
                break
              case this.FORM_TYPE_CHECKBOX:
                formData[prop] = false
                break
              default:
                formData[prop] = null
            }
        })

        this.formData = JSON.parse(JSON.stringify(formData))

        this.isFormInit = true
    },
    // placeholder统一设置
    setPlaceholder({ type, placeholder }) {
      console.log(type, placeholder)
        if(placeholder != undefined) {
            return placeholder
        } else {
            switch(type) {
                case this.FORM_TYPE_TEXT:
                case this.FORM_TYPE_PASSWORD:
                case this.FORM_TYPE_TEXTAREA:
                case this.FORM_TYPE_NUMBER:
                    return '请输入'
                case this.FORM_TYPE_SELECT:
                case this.FORM_TYPE_RADIO:
                case this.FORM_TYPE_CHECKBOX:
                case this.FORM_TYPE_CHECKBOX_GROUP:
                    return '请选择'
                default: 
                    return '请输入'
            }
        }
    },
    
    // 设置下拉列表的选项数据
    setOptions({ prop, options }) {
      const target = this.formList.find(item => item.prop === prop)
      if(target) {

        if(![this.FORM_TYPE_SELECT, this.FORM_TYPE_CASCADER].includes(target.type)) {
          console.warn(`${prop}的类型不正确,它没有options属性,${JSON.stringify(target)}`)
          return
        }

        target.options.splice(0, options.length)
        options.forEach(item => target.options.push(item))
        

      } else {
        console.warn(`${prop}不存在${JSON.stringify(this.formList)}中`)
      }
    },
    // 清空下拉列表
    clearOptions(prop) {
      const target = this.formList.find(item => item.prop === prop)
      if(target) {

        if(![this.FORM_TYPE_SELECT, this.FORM_TYPE_CASCADER].includes(target.type)) {
          console.warn(`${prop}的类型不正确,它没有options属性,${JSON.stringify(target)}`)
          return
        }
        target.options.splice(0, target.options.length)
        
      } else {
        console.warn(`${prop}不存在${JSON.stringify(this.formList)}中`)
      }
    },

    // 下拉框change事件处理
    handleSelectChange(item) {
      if(item.onChange) {
        this.$emit(item.onChange, this.formData, item)
      }
    },

    // 表单验证
    validate (callback) {
      this.$refs['form'].validate(callback)
    },
    // 特定字段验证
    validateField(prop) {
      this.$refs['form'].validateField(prop)
    },
    // 返回formData
    getFormData (opt) {
      const { dataType } = opt || {}
      if(dataType == 'FormData') {
        const formData = new FormData()
        this.formList.forEach(({ prop, type }) => {
          if(type == this.FORM_TYPE_FILE) {
            this.formData[prop].forEach(file => {
              formData.append(prop, file.raw)
            })
          } else {
            formData.append(prop, this.formData[prop])
          }
        })
        return formData
      } else {
        return this.formData
      }
    },
    // 设置formData
    setFormData (formData) {
      try {
        this.formList.forEach(({ prop, type }) => {
          if(typeof formData[prop] !== 'undefined') {
            if(type === this.FORM_TYPE_DATE) {
              this.formData[prop] = new Date(formData[prop])
            } else {
              this.formData[prop] = formData[prop]
            }
          }
        })
      } catch (err) {
        console.error(err)
      }
    },
    /* 文件表单 相关处理 */
    // 用户选择文件后的处理
    handleChangeFile({ prop, limit }, file, fileList) {
      this.formData[prop] = fileList
      // 专门对文件类型的字段进行重新验证
      this.$refs['form'].validateField(prop)
      return false
    },
    // 用户删除已选文件的处理
    removeFile(prop, index) {
      this.formData[prop].splice(index, 1)
      this.$refs['form'].validateField(prop)
    },
    
  },
  mounted () {
    this.initForm()
  }
}
</script>

<style lang="less" scoped>
.el-form {
  .el-form-item {
    .el-select,
    .el-date-editor,
    .el-cascader {
      width: 100%;
    }

    /* 文件类型表单样式 */
    .file__input__wrapper {
      border: 1px solid #DCDFE6;
      border-radius: 4px;
      position: relative;

      display: flex;
      justify-content: space-between;
      .file-list {
        padding: 0 4px;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        .file-item {
          color: #909399;
          line-height: 24px;
          background-color: #f4f4f5;
          border: 1px solid #e9e9eb;
          border-radius: 4px;
          padding: 0 8px;
          margin: 4px;
          display: flex;
          align-items: center;
          .icon-close {
            cursor: pointer;
            margin-left: 8px;
          }
          .icon-close:hover {
            color: red;
          }
        }
      }
      .placeholder {
        position: absolute;
        left: 8px;
        color: #c3c7cf;
        user-select: none;
      }
      :deep(.el-upload) {
        height: 100%;
        .upload-btn {
          background-color: #f5f7fa;
          color: #909399;
          border-left: 1px solid #dcdfe6;
          border-radius: 0 4px 4px 0;
          padding: 0 12px;
          white-space: nowrap;
          height: 100%;
          display: flex;
          align-items: center;
        }
      }
    }
    .file__input__wrapper:hover {
      border-color: #C0C4CC;
    }

    // 禁用样式
    .disabled {
      background-color: #f5f7fa;
      cursor: not-allowed;
    }
    .disabled:hover {
      border-color: #DCDFE6;
    }
  }
}


// 单列布局
.single-column {
  display: grid;
  grid-template-columns: 1fr;
}
// 两列布局
.double-column {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 100px;
}


</style>